#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#if (0)

#include "stimer.h"

#undef	TRACE_LEVEL 
#undef  TRACE_FUNN
#undef  TRACE_TITLE
#define	TRACE_LEVEL	TRACE_LEVEL_DEBUG
#define TRACE_FUNN	TRACE_FUNN_DISABLE
#define TRACE_TITLE "TIMER"
#include "trace.h"


#define HW_TIMER_ID		0

// extern int hw_timer_pause(int id);
// extern int hw_timer_resume(int id);
// extern unsigned int hw_timer_getticks(int id);

int hw_timer_pause(int id) {
	return 0;
}

int hw_timer_resume(int id) {
	return 0;
}

unsigned int hw_timer_getticks(int id) {
	return 0;
}


/* timer list */
static LIST_HEAD(TIMER_LIST);

/*
** @ timer execution should be in hardware timer interrupt
**/
int timer_exec(void) {
	struct list_head *pos;
	timer_t *timer;
	unsigned int systicks = hw_timer_getticks(HW_TIMER_ID);
	
	list_for_each(pos, &TIMER_LIST) {
		timer = list_entry(pos, timer_t, link_node);
		
		/* not running, continue */
		if (timer->status != TIMER_STATUS_RUNNING) {
			continue;
		}
		
		/* not timer-up, continue */
		if (timer->mark_tick > systicks) {
			continue;
		}
		
		/* call the callback function */
		if (timer->timeup_callback) {
			timer->timeup_callback(systicks);
		}
		
		switch(timer->type) {
		case TIMER_TYPE_ONETIME:
			/* mark timer as stop */
			timer->status = TIMER_STATUS_STOP;
		break;
		case TIMER_TYPE_OVERLOAD:
			timer->mark_tick = systicks + timer->interval;
			timer->over_times ++;
		break;
		default:
			break;
		}	
	}

	return 0;
}


/*
** @ Create timer by timer type, interval time and callback function
**/
timer_t *timer_create(enum TIMER_TYPE t, unsigned int interval, void (*callback)(unsigned int)) {
	timer_t *new_timer;
	
	new_timer = (timer_t *)malloc(sizeof(timer_t));
	if(new_timer == NULL)
		return NULL;
		
	switch(t) {
		case TIMER_TYPE_ONETIME:
		case TIMER_TYPE_OVERLOAD:
			new_timer->type = t;
			new_timer->interval = interval;
			new_timer->timeup_callback = callback;
			new_timer->start_tick = 0;
			new_timer->mark_tick = interval;
			new_timer->over_times = 0;
			new_timer->status = TIMER_STATUS_PAUSE;			
		break;
		default:
			free(new_timer);
			return NULL;	
	}
	hw_timer_pause(HW_TIMER_ID);
	list_add(&new_timer->link_node, &TIMER_LIST);	
	hw_timer_resume(HW_TIMER_ID);
	return new_timer;
}


/*
** @ Config timer mode
**/
static int timer_status_config(timer_t *timer, enum TIMER_STATUS new_status) {
	if (timer) {
		hw_timer_pause(HW_TIMER_ID);
		timer->status = new_status;
		hw_timer_resume(HW_TIMER_ID);
		return 0;
	}
	return -1;
}

/*
** @ Get system tick
**/
unsigned int timer_get_systick(timer_t *timer) {
	return hw_timer_getticks(HW_TIMER_ID);
}

/*
** @ Start timer
**/
int timer_start(timer_t *timer) {
	if(timer) {
		hw_timer_pause(HW_TIMER_ID);
		
		timer->start_tick = hw_timer_getticks(HW_TIMER_ID);
		timer->mark_tick = timer->start_tick + timer->interval;
		timer->status = TIMER_STATUS_RUNNING;
		
		hw_timer_resume(HW_TIMER_ID);
		return 0;
	} else {
		return -1;
	}
}

/*
** @ Resume timer
**/
int timer_resume(timer_t *timer) {
	return timer_status_config(timer, TIMER_STATUS_RUNNING);
}

/*
** @ Pause timer
**/
int timer_pause(timer_t *timer) {
	return timer_status_config(timer, TIMER_STATUS_PAUSE);
}

/*
** @ Stop timer
**/
int timer_stop(timer_t *timer) {
	return timer_status_config(timer, TIMER_STATUS_STOP);
}


/*
** @ Delete timer
**/
int timer_delete(timer_t *timer) {
	if (timer) {
		hw_timer_pause(HW_TIMER_ID);
		
		list_del(&timer->link_node);
		
		hw_timer_resume(HW_TIMER_ID);
		free(timer);
		return 0;
	}
	return -1;
}

/*
** @ Timer delay
**/
static int DELAY_TIMEOUT = 0;
static void timer_delay_callback(unsigned int tick) {
	DELAY_TIMEOUT = 1;
}
int timer_delay(int wtick) {
	timer_t *timer;
	
	timer = timer_create(TIMER_TYPE_ONETIME, wtick, timer_delay_callback);
	if (timer) {
		DELAY_TIMEOUT = 0;
		timer_start(timer);
		while(DELAY_TIMEOUT == 0);
		timer_stop(timer);
		timer_delete(timer);
		return 0;
	}
	return -1;
	
}


#if (0)
/*
** @ Timer test
**/
static int mark;
void timer_cb0(unsigned int tick) {
	TRACE_DEBUG("TIMER0 %d", tick);
}

void timer_cb_onetime(unsigned int tick) {
	TRACE_ERROR("FATAL TIMER %d", tick);
}

void timer_cb1(unsigned int tick) {
	if (mark == 1) {
		TRACE_FATAL("ERROR %d", tick);
	} else {
		TRACE_DEBUG("BING %d", tick);
	}
}

static int delay2(volatile unsigned int t) {
	while (t --);
	return 0;
}

int timer_test() {
#if (0)	
	timer_t *timer[10];
	int i;

	timer[0] = timer_create(TIMER_TYPE_OVERLOAD, 1000, timer_cb0);
	timer[1] = timer_create(TIMER_TYPE_OVERLOAD, 50, timer_cb1);
	timer_start(timer[0]);
	timer_start(timer[1]);
	
	while (1) {
		timer_pause(timer[1]);
		mark = 1;
		delay2(0xFFFF);
		mark = 0;
		timer_resume(timer[1]);
		delay2(0xFFFF);
	}
#endif
	while (1) {
		timer_delay(100);
		TRACE_DEBUG("TICK= %d", timer_get_systick(NULL));
	}
}
#endif

#endif




